44. Python内置函数

本章概要

  • 学习材料:数值序列、函数映射规则和筛选谓词。
  • 本章任务:使用map/filter/zip/enumerate完成转换、筛选与配对。
  • 完成后你将得到:转换列表、筛选列表、配对表和元素数量核对。
  • 自我检查:用列表推导式复算并核对顺序/长度;迭代器被提前耗尽时先检查原因。
  • 拓展练习:把内置函数方法应用到中国股票涨跌幅。

什么是Python内置函数?

  • Python内置函数(Built-in Functions)无需导入任何模块即可使用
  • 它们构成了Python编程的基础工具箱
  • 许多内置函数由底层实现优化,但倍数依硬件、版本、数据类型和规模而变;必须基准测试

内置函数的设计哲学

  • 高层抽象:隐藏底层实现细节,提供简洁接口
  • 泛型设计:同一函数可应用于多种数据类型
  • 性能优化:C语言底层实现,执行效率极高
  • 一致性:遵循统一的命名和调用约定

内置函数的功能分类

类别 代表函数 金融应用场景
数学运算 abs(), round(), sum() 收益计算,四舍五入
序列操作 len(), max(), min(), sorted() 价格排序,极值查找
迭代器 map(), filter(), zip() 数据转换,批量处理

内置函数分类:转换与输入输出

类别 代表函数 金融应用场景
类型转换 int(), float(), str() 数据清洗,类型转换
输入输出 print(), input(), open() 数据读取,结果输出

运行前预测|平台任务解答代码

  • 输入预测:运行前先写出 stockprofitprofit_totalprofit_average 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。
  • 结果预测:不展开答案,先预测将得到“2023年净利润排名前10位的证券公司净利润总和(亿元)”相关结果;同时写出方向、数量级或表格/图形结构。
  • 完成要求:能独立说明本任务从输入到“平台任务解答代码”结果的关键步骤,原样录入平台代码并得到可核对的运行结果。

⭐ 平台任务解答代码

展开完整代码(投影默认折叠)
# 注:该代码块包含未完成的填空代码,需要在平台上完成
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#任务一
stock = ["中信证券","华泰证券","国泰君安","招商证券","中国银河","广发证券","中信建投","国信证券","中金公司","申万宏源"]
print(len(stock)) #计算列表中元素的个数
print(list(enumerate(stock,start=1))) #创建带有索引并且以列表方式分输出


#任务二
profit = [205.39,130.36,98.85,87.69,78.84,78.63,70.47,64.27,61.64,54.75]
stock = ["中信证券","华泰证券","国泰君安","招商证券","中国银河","广发证券","中信建投","国信证券","中金公司","申万宏源"]  # 定义列表stock
profit_total = sum(profit)  #计算10家证券公司的净利润总和
profit_average = profit_total/len(stock)  # 获取数据长度

print("2023年净利润排名前10位的证券公司净利润总和(亿元)",profit_total)  # 输出2023年净利润排名前10位的证券公司净利润总和(
print("2023年净利润排名前10位的证券公司净利润平均数(亿元)",round(profit_average,4))  # 输出2023年净利润排名前10位的证券公司净利润平均数

#任务三
return_Q1 = [-0.0588,-0.0067,-0.0698,0.0239,-0.0059,-0.0672,-0.0739,-0.0193,-0.1543,0.0046]
return_max = max(return_Q1) #找出最大涨幅
return_min = min(return_Q1) #找出最小涨幅
print("2024年1季度股价的最大涨幅",return_max)  # 输出2024年1季度股价的最大涨幅
print("2024年1季度股价的最小涨幅",return_min)  # 输出2024年1季度股价的最小涨幅

price = [18.73,13.61,13.47,13.71,11.76,13.05,21.68,8.11,32.03,4.40]  # 定义列表price
price_sorted = sorted(price) #将股价由小到大排序
print(price_sorted)  # 输出价格数据

#任务四
stock = ["中信证券","华泰证券","国泰君安","招商证券","中国银河","广发证券","中信建投","国信证券","中金公司","申万宏源"]
# 定义列表code
code = ["600030","601688","601211","600999","601881","000776","601066","002736","601995","000166"]
profit = [205.39,130.36,98.85,87.69,78.84,78.63,70.47,64.27,61.64,54.75]  # 定义列表profit
# 定义列表return_Q1
return_Q1 = [-0.0588,-0.0067,-0.0698,0.0239,-0.0059,-0.0672,-0.0739,-0.0193,-0.1543,0.0046]
price = [18.73,13.61,13.47,13.71,11.76,13.05,21.68,8.11,32.03,4.40]  # 定义列表price
print(list(zip(stock,code,profit,return_Q1,price))) #将多个列表中对应的元素打包为一个元组并以列表方式输出

#任务五
fund = 1e7 #H公司的投资资金额
price_huatai = 13.76 #华泰证券股票
N = 100  # 设置期数/数量为100
share = N*int(fund/(price_huatai*N))  # 将数据转换为整数

print("H公司购买华泰证券的股票数量",share)  # 输出H公司购买华泰证券的股票数量

任务复盘|平台任务解答代码

运行后核对:核对 stockprofitprofit_totalprofit_average 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。

拓展练习:只改变一个关键输入或业务场景,先预测输出如何变化,再运行验证并解释变化原因。

len() — 获取序列长度

  • 语法len(序列)
  • 返回序列中元素的个数
  • 适用于字符串、列表、元组、字典等
  • 时间复杂度为 O(1),直接读取内部长度信息
numbers = [1, 2, 3, 4, 5]
print(f'长度: {len(numbers)}')
长度: 5

max()min() — 求极值

  • max() 返回序列中的最大值
  • min() 返回序列中的最小值
  • 可通过 key 参数指定比较依据
展开极值函数示例代码
numbers = [1, 2, 3, 4, 5]
print(f'最大值: {max(numbers)}')
print(f'最小值: {min(numbers)}')
最大值: 5
最小值: 1

max() / min() 的高级用法:key参数

  • key 参数指定用于比较的函数
  • 常用于字典列表中按某个键排序
展开 key 参数完整示例代码
# 找出PE最高和价格最低的股票
portfolio = [
    {'name': '茅台', 'price': 1850, 'pe': 45},
    {'name': '五粮液', 'price': 220, 'pe': 32},
    {'name': '招商银行', 'price': 45, 'pe': 8}
]

highest_pe = max(portfolio, key=lambda x: x['pe'])
print(f'PE最高: {highest_pe["name"]}, PE={highest_pe["pe"]}')

lowest_price = min(portfolio, key=lambda x: x['price'])
print(f'价格最低: {lowest_price["name"]}, 价格={lowest_price["price"]}')
PE最高: 茅台, PE=45
价格最低: 招商银行, 价格=45

sum() — 计算序列和

  • 语法sum(可迭代对象, 初始值=0)
  • 从左到右对元素求和
  • 只支持数值类型
numbers = [1, 2, 3, 4, 5]
print(f'求和: {sum(numbers)}')
求和: 15

sorted() — 排序

  • 返回排序后的新列表,原序列不变
  • reverse=True 可实现降序排序
  • Python的排序是稳定的(相等元素保持原顺序)
numbers = [1, 2, 3, 4, 5]
print(f'降序排序: {sorted(numbers, reverse=True)}')
降序排序: [5, 4, 3, 2, 1]

abs()round() — 数值处理

  • abs(x):返回绝对值
  • round(x, n):四舍五入到 n 位小数
print(f'绝对值: {abs(-10)}')
print(f'四舍五入: {round(3.14159, 2)}')
绝对值: 10
四舍五入: 3.14

注意:Python 3 的银行家舍入

  • Python 3 使用银行家舍入(Round Half to Even)
  • 当恰好为 0.5 时,舍入到最近的偶数
  • 目的是减少统计偏差
print(round(2.5))  # 2(最近的偶数)
print(round(3.5))  # 4(最近的偶数)

# 传统四舍五入需要使用 decimal 模块
from decimal import Decimal, ROUND_HALF_UP
print(Decimal('2.5').quantize(Decimal('1'), rounding=ROUND_HALF_UP))  # 3
2
4
3

pow() — 幂运算

  • 语法pow(底数, 指数) 等价于 底数 ** 指数
  • 支持模运算:pow(x, y, mod) 等价于 (x ** y) % mod
print(f'2的3次方: {pow(2, 3)}')
print(f'2的10次方对1000取模: {pow(2, 10, 1000)}')
2的3次方: 8
2的10次方对1000取模: 24

金融应用:基础统计量计算

# 收益率序列
returns = [0.05, -0.02, 0.03, 0.07, -0.01]

# 平均收益率
avg_return = sum(returns) / len(returns)
print(f'平均收益率: {avg_return:.2%}')

# 最大收益和最大亏损
print(f'最大收益: {max(returns):.2%}')
print(f'最大亏损: {min(returns):.2%}')

# 极差(Range)
range_value = max(returns) - min(returns)
print(f'收益极差: {range_value:.2%}')
平均收益率: 2.40%
最大收益: 7.00%
最大亏损: -2.00%
收益极差: 9.00%

map() — 映射函数到每个元素

  • 语法map(函数, 可迭代对象)
  • 返回迭代器,需用 list() 转换
  • 常用于批量数据类型转换
# 将字符串价格列表转换为浮点数
prices = ['10.5', '20.3', '15.8']
prices_float = list(map(float, prices))
print(f'转换为浮点数: {prices_float}')
转换为浮点数: [10.5, 20.3, 15.8]

filter() — 过滤元素

  • 语法filter(函数, 可迭代对象)
  • 函数返回 True 时保留元素
  • 常配合 lambda 表达式使用
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(f'偶数: {evens}')
偶数: [2, 4, 6, 8, 10]

zip() — 配对多个序列

  • 将多个序列对应位置的元素组合成元组
  • 最短序列为准
  • 常用于构造字典或并行遍历
names = ['张三', '李四', '王五']
ages = [25, 30, 35]

pairs = list(zip(names, ages))
print(f'配对: {pairs}')

# 直接构造字典
name_age_dict = dict(zip(names, ages))
print(f'字典: {name_age_dict}')
配对: [('张三', 25), ('李四', 30), ('王五', 35)]
字典: {'张三': 25, '李四': 30, '王五': 35}

enumerate() — 带索引遍历

  • 语法enumerate(可迭代对象, start=0)
  • 返回 (索引, 元素) 的迭代器
  • start 参数设置起始索引
stocks = ['茅台', '五粮液', '招行']
for index, stock in enumerate(stocks, start=1):
    print(f'{index}. {stock}')
1. 茅台
2. 五粮液
3. 招行

map() / filter() 与列表推导式对比

  • 列表推导式通常更Pythonic、更易读
  • 功能上两者等价
numbers = [1, 2, 3, 4, 5]

# map + lambda
squared_map = list(map(lambda x: x**2, numbers))

# 列表推导式(推荐)
squared_comp = [x**2 for x in numbers]

print(f'map方式: {squared_map}')
print(f'推导式: {squared_comp}')
map方式: [1, 4, 9, 16, 25]
推导式: [1, 4, 9, 16, 25]

zip() 的解包操作

  • zip(*) 可实现反向解包
  • 将元组列表拆分为多个独立序列
# zip 配对
matrix = [(1, 'a'), (2, 'b'), (3, 'c')]

# zip(*) 解包
numbers, letters = zip(*matrix)
print(f'数字: {numbers}')
print(f'字母: {letters}')
数字: (1, 2, 3)
字母: ('a', 'b', 'c')

金融应用:数据清洗处理流程

# 原始数据:字符串格式的价格和数量
raw_data = [
    ('10.5', '100'),
    ('20.3', '200'),
    ('15.8', '150')
]

# 使用 map() 进行数据转换
prices = list(map(lambda x: float(x[0]), raw_data))
quantities = list(map(lambda x: int(x[1]), raw_data))

# 计算每笔交易金额
amounts = list(map(lambda p, q: p * q, prices, quantities))
print(f'交易金额: {amounts}')

# 过滤出金额大于2000的交易
large_trades = list(filter(lambda x: x > 2000, amounts))
print(f'大额交易: {large_trades}')
交易金额: [1050.0, 4060.0, 2370.0]
大额交易: [4060.0, 2370.0]

金融应用:计算最大回撤

  • 最大回撤是从峰值到谷底的最大跌幅
  • 是评估投资策略风险的关键指标
returns = [0.05, -0.02, 0.03, 0.07, -0.01]

cum_return = 1.0   # 初始累计收益
max_drawdown = 0    # 最大回撤
peak = 1.0          # 历史峰值

for r in returns:
    cum_return *= (1 + r)          # 更新累计收益
    if cum_return > peak:
        peak = cum_return          # 更新历史峰值
    drawdown = (peak - cum_return) / peak  # 计算当前回撤
    max_drawdown = max(max_drawdown, drawdown)

print(f'最大回撤: {max_drawdown:.2%}')
最大回撤: 2.00%

金融应用:简化版夏普比率

  • 夏普比率衡量单位风险的超额收益
  • 公式:\(\text{Sharpe} = \frac{\bar{R} - R_f}{\sigma}\)
import math

returns = [0.05, -0.02, 0.03, 0.07, -0.01]
mean = sum(returns) / len(returns)

# 计算标准差
variance = sum((r - mean) ** 2 for r in returns) / len(returns)
std_dev = math.sqrt(variance)

# 假设无风险利率2%(年化),252个交易日
risk_free_rate = 0.02
sharpe_ratio = (mean * 252 - risk_free_rate) / (std_dev * math.sqrt(252))
print(f'年化夏普比率: {sharpe_ratio:.2f}')
年化夏普比率: 11.04

金融应用:正收益天数与分位数

returns = [0.05, -0.02, 0.03, 0.07, -0.01]

# 统计正收益天数
positive_count = len([r for r in returns if r > 0])
print(f'正收益次数: {positive_count}/{len(returns)}')

# 计算中位数
sorted_returns = sorted(returns)
n = len(sorted_returns)
if n % 2 == 0:
    median = (sorted_returns[n//2 - 1] + sorted_returns[n//2]) / 2
else:
    median = sorted_returns[n//2]
print(f'中位数收益率: {median:.2%}')
正收益次数: 3/5
中位数收益率: 3.00%

all()any() 函数

  • all()所有元素为 True 时返回 True
  • any()任一元素为 True 时返回 True
returns = [0.01, 0.02, 0.03, -0.01, 0.02]

print(f'所有收益为正: {all(r > 0 for r in returns)}')
print(f'存在负收益: {any(r < 0 for r in returns)}')

# 检查投资组合权重归一化
weights = [0.3, 0.4, 0.3]
print(f'权重之和为1: {abs(sum(weights) - 1.0) < 1e-10}')
所有收益为正: False
存在负收益: True
权重之和为1: True

最佳实践总结

  • 优先使用内置函数:C实现、性能好、代码简洁
  • 列表推导式 > map/filter:更Pythonic、更易读
  • 大规模数值计算评估NumPy:优势依运算、dtype、规模与内存布局而变,以本机基准为准
  • 避免修改正在遍历的列表:使用推导式创建新列表

常见陷阱

# 陷阱:修改正在遍历的列表
lst = [1, 2, 3, 4, 5]
# ❌ 错误做法:for item in lst: lst.remove(item)
# ✅ 正确做法:创建新列表
lst_odd = [x for x in lst if x % 2 != 0]
print(f'过滤偶数后: {lst_odd}')

# 陷阱:可变默认参数
def foo(lst=None):
    if lst is None:
        lst = []
    lst.append(1)
    return lst

print(foo())  # [1]
print(foo())  # [1](每次调用都是新列表)
过滤偶数后: [1, 3, 5]
[1]
[1]

随堂练习

  • 问题 1|需要准备哪些数据?:数值序列、函数映射规则和筛选谓词。
  • 问题 2|需要完成哪些操作?:使用map/filter/zip/enumerate完成转换、筛选与配对。
  • 问题 3|应得到哪些结果?:转换列表、筛选列表、配对表和元素数量核对。
  • 问题 4|怎样确认结果可靠?:用列表推导式复算并核对顺序/长度;迭代器被提前耗尽时先检查原因。
  • 问题 5|换一个情境,怎样继续应用?:把内置函数方法应用到中国股票涨跌幅。
  • 作答提示:请依次写清所用数据、分析过程、所得结果、核对方法和拓展思考。课程所需数据见前言中的下载入口;教学平台固定题按页面说明完成。

教师参考解答|答案与说明 1

  • 所用数据与字段:小数收益率列表;变换后仍为有限浮点数。

教师参考解答|代码 1

展开代码(代码区可独立滚动)
returns=[.01,-.02,.03,0]  # 建立确定性收益输入
percent=list(map(lambda x:100*x,returns))  # 建立确定性收益输入
positive=list(filter(lambda x:x>0,returns))  # 建立确定性收益输入
ordered=sorted(returns)  # 建立确定性收益输入
checks={'all_finite':all(x==x for x in returns),'has_loss':any(x<0 for x in returns)}  # 记录每个分箱或条件的核对依据
assert percent==[1,-2,3,0] and positive==[.01,.03]  # 把小数收益转换为百分点列表
assert returns==[.01,-.02,.03,0]  # 建立确定性收益输入
print(percent,positive,ordered,checks)  # 记录每个分箱或条件的核对依据

教师参考解答|答案与说明 2

  • 解释答案:map 转换、filter 筛选、sorted 排序、all/any 汇总条件各自对应不同依据;链式使用前应保留原序列并明确返回类型。
  • 拓展应用答案:拓展应用到订单折扣序列时,计算百分数、筛选异常折扣、排序并检查有限值,用列表期望值与原输入不变检查核对。
  • 参考结果:百分数、正收益、排序副本和布尔检查。另行核对:用列表推导式得到同结果并确认 sorted 未改原表。
  • 常见错误:忘记将迭代器转列表;混淆 sort 返回值;把未经实测的性能倍数当普遍事实。